<?php

class DB_CRUD {
    protected $db;
    protected $table;
    protected $PK;
    protected $fields;

    public function __construct($db) {
        $this->db = $db;
    }

    public function save($data) {
        $record = $this->read($data);
        if ($record) {
            return $this->update($data);
        } else {
            return $this->create($data);
        }
    }

    public function create($data) {
        $sql = $this->getInsertStatement($data);
        if (!$sql) {
            return false;
        }
        $sth = $this->db->prepare($sql);
        $this->assignValues($sth, $data);
        $sth->execute();
        return true;
    }

    public function read($data) {
        $sql = "SELECT * FROM {$this->table} WHERE {$this->PK} = :{$this->PK}";
        $sth = $this->db->prepare($sql);
        $sth->bindValue(":{$this->PK}", $data->{$this->PK});
        $sth->execute();
        return $sth->fetch(PDO::FETCH_ASSOC);
    }

    public function update($data) {
        $sql = $this->getUpdateStatement($data);
        if (!$sql) {
            return false;
        }
        $sth = $this->db->prepare($sql);
        $sth->bindValue(":{$this->PK}", $data->{$this->PK});
        $this->assignValues($sth, $data);
        $sth->execute();
    }

    public function delete($data) {
        $sql = "DELETE FROM {$this->table} WHERE {$this->PK} = :{$this->PK}";
        $sth = $this->db->prepare($sql);
        $sth->bindValue(":{$this->PK}", $data->{$this->PK});
        $sth->execute();
    }

    protected function getInsertStatement($data) {
        $fieldList = array();
        $valueList = array();
        foreach ($this->fields as $field) {
            if (!isset($data->$field)) {
                continue;
            }
            $fieldList[] = $field;
            $valueList[] = ':' . $field;
        }
        if (sizeof($fieldList) == 0) {
            return false;
        }
        $sql = "INSERT INTO {$this->table} (" . implode(',', $fieldList) . ") VALUES (" . implode(',', $valueList) . ")";
        return $sql;
    }

    protected function getUpdateStatement($data) {
        $updateList = array();
        foreach ($this->fields as $field) {
            if (!isset($data->$field)) {
                continue;
            }
            $updateList[] = $field . ' = :' . $field;
        }
        if (sizeof($updateList) == 0) {
            return false;
        }
        $sql = "UPDATE {$this->table} SET " . implode(',', $updateList) . " WHERE {$this->PK} = :{$this->PK}";
        return $sql;
    }

    protected function assignValues($sth, $data) {
        foreach ($this->fields as $field) {
            if (!isset($data->$field)) {
                continue;
            }
            $sth->bindValue(':' . $field, $data->$field);
        }
    }
}
